﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Security;
using System.Security.Permissions;
using SipII.Parameter;

namespace SipII
{
    partial class SocketServer
    {
        /// <summary>
        /// 开始一个异步操作来接受一个传入的连接尝试并创建一个新的 Socket 来处理远程的主机通信
        /// </summary>     
        /// <param name="ar">异步操作的状态信息
        /// </param> 
        public static void AcceptCallback(IAsyncResult ar)
        {
            Socket listener = null;

            // 一个新的处理远程主机通信的 Socket 
            Socket handler = null;

            try
            {
                // 接收 byte 数组
                byte[] buffer = new byte[1024];

                // 得到侦听 Socket 对象
                listener = (Socket)ar.AsyncState;

                // 异步接受传入的连接尝试，并创建新的 Socket 来处理远程主机通信
                handler = listener.EndAccept(ar);

                // 使用 Nagle 算法
                handler.NoDelay = true;

                // 创建传递数据的对象数字
                object[] obj = new object[2];
                obj[0] = buffer;
                obj[1] = handler;

                // 开始从连接的 Socket 中异步接收数据
                handler.BeginReceive(
                    buffer,        // 存储接收到的数据的 Byte 类型的数组
                    0,             // buffer 参数中存储所接收数据的位置 
                    buffer.Length, // 要接收的字节数
                    SocketFlags.None,// 套接字的发送和接收行为
                    new AsyncCallback(ReceiveCallback),//一个 AsyncCallback 委托调用操作完成时要执行的方法
                    obj            // 包含接收操作的相关信息
                    );

                // 开始一个异步操作来接受一个传入的连接尝试
                AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
                listener.BeginAccept(aCallback, listener);
            }
            catch (Exception ex)
            {
                logWritor.Output(string.Format("Exception: {0}", ex.ToString()));
            }
        }

        /// <summary>
        /// 从连接的 Socket 中异步接收数据
        /// </summary>
        /// <param name="ar">
        /// 异步操作状态
        /// </param> 
        public static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // 获取包含信息的用户自定义对象
                object[] obj = new object[2];
                obj = (object[])ar.AsyncState;

                // 获取存放接收数据的 byte 数字
                byte[] buffer = (byte[])obj[0];

                // 处理远程通信的 Socket 对象
                Socket handler = (Socket)obj[1];

                // 接收消息
                string content = string.Empty;

                // 接收到的字节数
                int bytesRead = handler.EndReceive(ar);

                if (bytesRead > 0)
                {
                    content += Encoding.UTF8.GetString(buffer, 0,
                        bytesRead);

                    // 如果消息包含发送终止符, 完成数据接收
                    if (content.EndsWith(Sip2Parameter.MessageTerminator))
                    {
                        // 将字节数组转换成字符串
                        string requestCmd = content.Substring(0, content.LastIndexOf(Sip2Parameter.MessageTerminator));

                        logWritor.Output(string.Format("Read {0} bytes from {1}.\n Data: {2}", requestCmd.Length, ((IPEndPoint)handler.RemoteEndPoint).Address, requestCmd));
                       
                        // 响应请求并获取回复信息
                        string responseCmd = Sip2ServerProxy.Response(((IPEndPoint)handler.RemoteEndPoint).Address.ToString(), requestCmd);

                        byte[] byteData = Encoding.UTF8.GetBytes(responseCmd);

                        // 异步发送回复信息
                        handler.BeginSend(byteData, 0, byteData.Length, 0,
                            new AsyncCallback(SendCallback), handler);
                        
                    }
                    else
                    {
                        // 持续异步接收数据
                        byte[] buffernew = new byte[1024];
                        obj[0] = buffernew;
                        obj[1] = handler;
                        handler.BeginReceive(buffernew, 0, buffernew.Length,
                            SocketFlags.None,
                            new AsyncCallback(ReceiveCallback), obj);
                    }
                }
            }
            catch (Exception ex)
            {
                logWritor.Output(string.Format("Exception: {0}", ex.ToString()));
            }
        }

        /// <summary>
        /// 向连接的 Socket 异步发送数据
        /// </summary>
        /// <param name="ar">
        /// 异步操作状态
        /// </param> 
        public static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // 获取向远程主机发送数据的 Socket 对象
                Socket handler = (Socket)ar.AsyncState;

                // 发送数据字节数
                int bytesSend = handler.EndSend(ar);
                
                logWritor.Output(string.Format("Sent {0} bytes to Client", bytesSend));
            }
            catch (Exception ex)
            {
                logWritor.Output(string.Format("Exception: {0}", ex.ToString()));
            }
        }
    }
}
